/* 
 * File:   main.c
 * Author: Yannic
 *
 * Created on 14. Mai 2013, 20:49
 */

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "bmpHeader.h"

struct tagRGBQUAD** Make2DPixelArray(int arraySizeX, int arraySizeY);
//void savePixelTo24BitBmp(struct tagRGBQuad , int width, int height); 

int main(void)
{
  FILE* bmpFile;
  FILE* saveBmpFile;
  struct tagBITMAPFILEHEADER bitmapFileHeader;
  struct tagBITMAPINFOHEADER bitmapInfoHeader;
  struct tagRGBQUAD** bmpArray;
  struct tagRGBQUAD* bmpColors;
  int size_bmpColors;
  int i, x, y;
  unsigned char rleData;
  unsigned char rleDataIndex;
  unsigned char test[4];
  unsigned char colorIndex;
  unsigned char wordBoundaryVal;
  
  bmpFile = fopen("aufgabe4_bild3_komp.bmp", "rb"); // Datei zum lesen öffnen
  
  if (bmpFile != NULL) { // Datei erfolgreich geöffnet ?
     fread(&bitmapFileHeader, 1, sizeof(bitmapFileHeader), bmpFile); 
     fread(&bitmapInfoHeader, 1, sizeof(bitmapInfoHeader), bmpFile);

     int size_BmpColors = ((int)pow(2, bitmapInfoHeader.biBitCount)) * sizeof(struct tagRGBQUAD);
     bmpColors = malloc(size_BmpColors);
     
     for(i=0; i < (size_BmpColors / sizeof(struct tagRGBQUAD)); i++) {
         fread(&bmpColors[i], 1, sizeof(struct tagRGBQUAD*), bmpFile);     
     }
     
     
     //printf("%d ---- %d\n", bitmapInfoHeader.biWidth, bitmapInfoHeader.biHeight);
     bmpArray = Make2DPixelArray(bitmapInfoHeader.biWidth, bitmapInfoHeader.biHeight); // Dynamisch das Array für unsere Bitmap erzeugen   
     
     // Einlesen einer unkomprimierten Bitmap mit Farbpalette
     /*for(x=0; x < bitmapInfoHeader.biHeight; x++) {
         for(y=0; y < bitmapInfoHeader.biWidth; y++) {
             fread(&colorIndex, 1, 1, bmpFile);
             
             bmpArray[y][x].rgbRed = bmpColors[colorIndex].rgbRed;   
             bmpArray[y][x].rgbGreen = bmpColors[colorIndex].rgbGreen;
             bmpArray[y][x].rgbBlue = bmpColors[colorIndex].rgbBlue;     
         }     
     }*/
     
     // Einlesen einer RLE komprimietren Bitmap
     x = 0;
     y = 0;
     rleDataIndex = 0;
     
     while(fread(&rleData, 1, 1, bmpFile) != 0) {
	test[rleDataIndex] = rleData;
        rleDataIndex++;  
		
        if ((rleDataIndex >= 2) && (test[0] == 0)) { // Wenn ein Bytepaar ausgelesen und 1 Byte = 0
	   if (test[1] == 0) { // End of Line
              y++;
              x = 0;
              rleDataIndex = 0;
           }
           if (test[1] == 1) { // End of Bitmap
              break;
           } 
           if (test[1] == 2) { // Delta
              if (rleDataIndex == 4) {
                 x += test[2];
                 y += test[3];
                 rleDataIndex = 0;                                  
              }                 
           }
           if (test[1] >= 3) { // Absolute Mode // Achtung Wortgrenze muss noch berücksichtigt werden
               //Wortgrenze sicherstellen
               wordBoundaryVal = ((test[1] % 2) != 0) ? test[1] + 1 : test[1];
               
               for(i=0; i < wordBoundaryVal; i++) {
              	  fread(&rleData, 1, 1, bmpFile);
                  if (i < test[1]) {
                      bmpArray[x][y].rgbRed = bmpColors[rleData].rgbRed;   
                      bmpArray[x][y].rgbGreen = bmpColors[rleData].rgbGreen;
                      bmpArray[x][y].rgbBlue = bmpColors[rleData].rgbBlue;
                      x++;
                  }
               }         
               rleDataIndex = 0;              
           }
        } else {
           if ((rleDataIndex == 2) && (test[0] != 0)) { // Bytepaar ausgelesen und 1. Byte != 0
              for(i=0; i<test[0]; i++) {
                 bmpArray[x][y].rgbRed = bmpColors[test[1]].rgbRed;   
                 bmpArray[x][y].rgbGreen = bmpColors[test[1]].rgbGreen;
                 bmpArray[x][y].rgbBlue = bmpColors[test[1]].rgbBlue;
                 x++;
              }                   
              rleDataIndex = 0; // Zeiger zurücksetzen 
           }                         
        }                                      
     }     
     
    
     // 8Bit Bitmap ---> 24Bit Bitmap
     saveBmpFile = fopen("test.bmp", "wb"); // Datei zum speichern anlegen 
     if (saveBmpFile != NULL) {
        bitmapFileHeader.bfSize = (bitmapInfoHeader.biWidth * bitmapInfoHeader.biHeight * 3) + 54;
        bitmapFileHeader.bfOffBits = 54;               
                     
        bitmapInfoHeader.biBitCount = 24;
        bitmapInfoHeader.biClrUsed = 0;
        bitmapInfoHeader.biClrImportant = 0;
        bitmapInfoHeader.biSizeImage = (bitmapInfoHeader.biWidth * bitmapInfoHeader.biHeight * 3); 
        //
        bitmapInfoHeader.biCompression = 0;
                    
        fwrite(&bitmapFileHeader, 1, sizeof(bitmapFileHeader), saveBmpFile); // Schreibe Bitmap Dateiheader   
        fwrite(&bitmapInfoHeader, 1, sizeof(bitmapInfoHeader), saveBmpFile); // Schreibe Bitmap Infoheader
        
        for(x=0; x < bitmapInfoHeader.biHeight; x++) {
            for(y=0; y < bitmapInfoHeader.biWidth; y++) {
                fwrite(&bmpArray[y][x].rgbBlue, 1, 1, saveBmpFile); // Schreibe Blauen Farbwert
                fwrite(&bmpArray[y][x].rgbGreen, 1, 1, saveBmpFile); // Schreibe Grünen Farbwert  
                fwrite(&bmpArray[y][x].rgbRed, 1, 1, saveBmpFile); // Schreibe Roten Farbwert
            } 
        }                      
     } 
     fclose(saveBmpFile);   
     
    
  }
  
  fclose(bmpFile); // Datei wieder freigeben        
  
  system("PAUSE");	
  return 0;
}

struct tagRGBQUAD** Make2DPixelArray(int arraySizeX, int arraySizeY) {  
    struct tagRGBQUAD** theArray;  
    int i;
    theArray = (struct tagRGBQUAD**) malloc(arraySizeX*sizeof(struct tagRGBQUAD*));  
    if (theArray == NULL) {
         return NULL;
    } 
    
    for (i = 0; i < arraySizeX; i++) {  
        theArray[i] = (struct tagRGBQUAD*) malloc(arraySizeY*sizeof(struct tagRGBQUAD));      
        if (theArray[i] == NULL) return NULL;
    }    
    return theArray;                 
} 

/*void savePixelTo24BitBmp(struct tagRGBQuad , int width, int height) {
     int x = 0;
     int y = 0;
     FILE* saveBmpFile;
     
     saveBmpFile = fopen("test.bmp", "wb"); // Datei zum speichern anlegen 
     if (saveBmpFile != NULL) {
        for(x = 0; x < width; x++){
           for(y = 0; y < height; y++){
              fwrite(bmpArray[y][x].rgbRed, 1, 1, saveBmpFile); // Schreibe Daten 
              fwrite(bmpArray[y][x].rgbGreen, 1, 1, saveBmpFile); // Schreibe Daten 
              fwrite(bmpArray[y][x].rgbBlue, 1, 1, saveBmpFile); // Schreibe Daten 
           }
        }
     }
     
     fclose(saveBmpFile);   
}  */
